#include "../include/ftp_test.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <regex.h>
#include <ctype.h>
#include <stdlib.h>

int ftp_send_command(int sockfd, const char* command, const char* arg) {
    char buffer[FTP_MAX_CMD_LEN];
    int len ;

    if(arg == NULL||arg[0] == '\0'){
        len = snprintf(buffer, sizeof(buffer), "%s\r\n", command);
    }else{
        len = snprintf(buffer,sizeof(buffer), "%s %s\r\n",command,arg);
    }

    if(len<0 || len>=(int)sizeof(buffer)){
        return -1;
    }

    return send(sockfd, buffer, len, MSG_NOSIGNAL) == len ? 0 : -1;
}

int ftp_read_response(int sockfd, char* response, size_t max_len) {
    size_t received = 0;
    int code_pos = -1;
    
    while (received < max_len - 1) {
        ssize_t n = recv(sockfd, response + received, 1, 0);
        if (n <= 0) return -1;

        received++;
        response[received] = '\0';
        
        // 检测每行的结束
        if (received >= 2 && 
            response[received-2] == '\r' && 
            response[received-1] == '\n') {
            
            // 找到第一个三位数字
            for (size_t i = 0; i <= received-5; i++) {
                if (isdigit(response[i]) && 
                    isdigit(response[i+1]) && 
                    isdigit(response[i+2]) &&
                    response[i+3] == ' ') {
                    code_pos = i;
                    break;
                }
            }
            
            if (code_pos != -1) {
                response[received+1] = '\0';
                return 0;
            }
        }
        received++;
    }
    return -1;
}

int ftp_parse_pasv(const char* response, char* ip, int* port) {
    regex_t regex;
    regmatch_t matches[7];
    const char* pattern = ".*?([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+),([0-9]+)";
    
    if (regcomp(&regex, pattern, REG_EXTENDED)) return -1;
    
    if (regexec(&regex, response, 7, matches, 0) == REG_NOMATCH) {
        regfree(&regex);
        return -1;
    }
    
    int nums[6];
    for (int i = 0; i < 6; i++) {
        char num[4] = {0};
        strncpy(num, response + matches[i+1].rm_so, 
               matches[i+1].rm_eo - matches[i+1].rm_so);
        nums[i] = atoi(num);
    }
    
    snprintf(ip, 16, "%d.%d.%d.%d", nums[0], nums[1], nums[2], nums[3]);
    *port = (nums[4] << 8) + nums[5];
    
    regfree(&regex);
    return 0;
}

int ftp_data_connect(const char* ip, int port) {
    int data_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (data_fd < 0) return -1;

    struct sockaddr_in addr = {
        .sin_family = AF_INET,
        .sin_port = htons(port),
    };
    addr.sin_addr.s_addr = inet_addr(ip);
    if(addr.sin_addr.s_addr == INADDR_NONE){
        close(data_fd);
        return -1;
    }
    
    if (connect(data_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        close(data_fd);
        return -1;
    }
    return data_fd;
}

int ftp_login(int ctrl_fd, const char* user, const char* pass) {
    char response[FTP_MAX_RESPONSE];
    
    // Send USER command
    if (ftp_send_command(ctrl_fd, FTP_CMD_USER, user) < 0) return -1;
    if (ftp_read_response(ctrl_fd, response, sizeof(response)) < 0) return -1;
    
    // Check if password needed (331)
    int code;
    sscanf(response, "%d", &code);
    if (code != FTP_RESPONSE_NEED_PASSWORD) return -1;
    
    // Send PASS command
    if (ftp_send_command(ctrl_fd, FTP_CMD_PASS, pass) < 0) return -1;
    if (ftp_read_response(ctrl_fd, response, sizeof(response)) < 0) return -1;
    
    sscanf(response, "%d", &code);
    return code == FTP_RESPONSE_USER_LOGGED_IN ? 0 : -1;
}

int ftp_set_binary_mode(int ctrl_fd) {
    char response[FTP_MAX_RESPONSE];
    if (ftp_send_command(ctrl_fd, FTP_CMD_TYPE, "I") < 0) return -1;
    if (ftp_read_response(ctrl_fd, response, sizeof(response)) < 0) return -1;
    
    int code;
    sscanf(response, "%d", &code);
    return code == FTP_RESPONSE_OK ? 0 : -1;
}
